package com.yanqu.road.server.manger;

import com.yanqu.road.entity.activity.shuihuyezipai.ShuiHuYeZiCardBattleCard;
import com.yanqu.road.entity.activity.shuihuyezipai.ShuiHuYeZiCardDiscardCard;
import com.yanqu.road.entity.activity.shuihuyezipai.ShuiHuYeZiCardPlayRecord;
import com.yanqu.road.entity.activity.shuihuyezipai.ShuiHuYeZiCardRoomData;
import com.yanqu.road.entity.activity.shuihuyezipai.config.ShuiHuYeZiCardActivityConfig;
import com.yanqu.road.entity.activity.shuihuyezipai.config.ShuiHuYeZiCardBuffConfig;
import com.yanqu.road.entity.activity.shuihuyezipai.config.ShuiHuYeZiCardCardConfig;
import com.yanqu.road.pb.activity.ShuiHuYeZiCardProto;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.*;

/**
 * 水浒叶子牌
 */
public abstract class AbstractShuiHuYeZiCardRoom {

    private static final Logger logger = LogManager.getLogger(AbstractShuiHuYeZiCardRoom.class.getName());

    private ShuiHuYeZiCardRoomData roomInfo;

    private static Random random = new Random();

    public AbstractShuiHuYeZiCardRoom(ShuiHuYeZiCardRoomData roomInfo) {
        this.roomInfo = roomInfo;
    }

    /**
     * 开始比赛
     */
    abstract public boolean startGame();

    /**
     * 发牌
     */
    public List<List<Integer>> dealCard(ShuiHuYeZiCardActivityConfig activityConfig) {
        List<List<Integer>> list = new ArrayList<>(2);
        List<ShuiHuYeZiCardCardConfig> cardList = new ArrayList<>(activityConfig.getCardConfigMap().values());
        Collections.shuffle(cardList);
        // 上一轮大的玩家
        List<Integer> cardList1 = new ArrayList<>();
        int totalValue1 = 0;
        List<Integer> cardList2 = new ArrayList<>();
        int totalValue2 = 0;

        for (int i = 0; i < 8; i++) {
            ShuiHuYeZiCardCardConfig card1 = cardList.remove(0);
            ShuiHuYeZiCardCardConfig card2 = null;
            int diff = 0;
            for (ShuiHuYeZiCardCardConfig item : cardList) {
                int tempDiff = Math.abs(item.getPoint() - card1.getPoint());
                if (diff == 0 || tempDiff < diff) {
                    card2 = item;
                    diff = tempDiff;
                }
                if (tempDiff <= activityConfig.SHUIHUYEZICARD_MAX_POINTS_DIFF) {
                    break;
                }
            }
            cardList.remove(card2);
            if ((totalValue1 > totalValue2 && card1.getPoint() < card2.getPoint()) ||
                    (totalValue1 < totalValue2 && card1.getPoint() > card2.getPoint())) {
                cardList1.add(card1.getId());
                totalValue1 += card1.getPoint();

                cardList2.add(card2.getId());
                totalValue2 += card2.getPoint();
            } else {
                cardList1.add(card2.getId());
                totalValue1 += card2.getPoint();

                cardList2.add(card1.getId());
                totalValue2 += card1.getPoint();
            }
        }
        list.add(cardList1);
        list.add(cardList2);

        for (ShuiHuYeZiCardCardConfig item : cardList) {
            ShuiHuYeZiCardDiscardCard discardCard = new ShuiHuYeZiCardDiscardCard();
            discardCard.setId(item.getId());
            getRoomInfo().getDiscardList().add(discardCard);
        }

//        logger.info("水浒叶子牌分牌 手牌1：{} 总点数：{}，手牌2：{}，总点数：{}。",cardList1,calTotalCardPoint(activityConfig,cardList1),cardList2,calTotalCardPoint(activityConfig,cardList2));
        return list;
    }


    /**
     * 回合结束
     *
     * @param activityConfig
     * @return 是否替换buff
     */
    public boolean roundOver(ShuiHuYeZiCardActivityConfig activityConfig) {
        roomInfo.setNum(roomInfo.getNum() - 1);
        roomInfo.setRound(roomInfo.getRound() + 1);
        return touchBuff(activityConfig);
    }

    /**
     * 触发buff事件
     *
     * @param activityConfig
     * @return 是否替换buff
     */
    public boolean touchBuff(ShuiHuYeZiCardActivityConfig activityConfig) {
        boolean touchBuff = false;
        if (roomInfo.getRound() == 1) {
            // 初始化
            roomInfo.setBuffId(randomBuffId(activityConfig, roomInfo.getRound(), 0));
            roomInfo.setNum(randomBuffNum(activityConfig, roomInfo.getBuffId()));
            roomInfo.setNextBuffId(randomBuffId(activityConfig, roomInfo.getRound() + roomInfo.getNum(), roomInfo.getBuffId()));
        } else {
            if (roomInfo.getNum() <= 0) {
                roomInfo.setBuffId(roomInfo.getNextBuffId());
                roomInfo.setNum(randomBuffNum(activityConfig, roomInfo.getBuffId()));
                roomInfo.setNextBuffId(randomBuffId(activityConfig, roomInfo.getRound() + roomInfo.getNum(), roomInfo.getBuffId()));
                touchBuff = true;
            }
        }
        refreshCard(activityConfig);
        return touchBuff;
    }

    /**
     * 出牌
     */
    abstract public int playCard(long userId, int id, int round);


    /**
     * 自动出牌
     */
    abstract public ShuiHuYeZiCardBattleCard autoPlayCard();

    /**
     * 比大小
     */
    public long battle(ShuiHuYeZiCardBattleCard playCard1, long playId1, boolean isAutoPlay1, ShuiHuYeZiCardBattleCard playCard2, long playId2, boolean isAutoPlay2) {
        long winnerId = 0;
        if (playCard1.getValue() == playCard2.getValue()) {
            // 平局 全部加入弃牌堆
            getRoomInfo().getDiscardList().add(copyShuiHuYeZiCardBattleCard(playCard1));
            getRoomInfo().getDiscardList().add(copyShuiHuYeZiCardBattleCard(playCard2));
        } else {
            if (playCard1.getValue() > playCard2.getValue()) {
                // 获得 player2 的牌
                getRoomInfo().getUserCardMap().get(playId1).put(playCard2.getId(), playCard2);
                getRoomInfo().getDiscardList().add(copyShuiHuYeZiCardBattleCard(playCard1));
                winnerId = playId1;
            } else {
                // 获得 player1 的牌
                getRoomInfo().getUserCardMap().get(playId2).put(playCard1.getId(), playCard1);
                getRoomInfo().getDiscardList().add(copyShuiHuYeZiCardBattleCard(playCard2));
                winnerId = playId2;
            }
            getRoomInfo().setLastRoundWinnerId(winnerId);
        }

        // 加入回合数据
        ShuiHuYeZiCardPlayRecord record = new ShuiHuYeZiCardPlayRecord();
        record.setRound(getRoomInfo().getRound());
        record.getRecordMap().put(playId1, new ShuiHuYeZiCardBattleCard(playCard1.getId(), playCard1.getLevel(), playCard1.getQuality(), playCard1.getValue(), isAutoPlay1));
        record.getRecordMap().put(playId2, new ShuiHuYeZiCardBattleCard(playCard2.getId(), playCard2.getLevel(), playCard2.getQuality(), playCard2.getValue(), isAutoPlay2));
        record.setWinnerId(winnerId);
        record.setBuffId(getRoomInfo().getBuffId());
        getRoomInfo().getRecordList().add(record);

        return winnerId;
    }


    /**
     * 广播回合信息
     *
     * @param curRound
     * @param winnerId
     * @param playerId1
     * @param playCard1
     * @param playerId2
     * @param playCard2
     * @param roundTime
     * @param buffId
     * @param roomType  房间类型（0练习模式 1pve  2pvp）
     * @return
     */
    public ShuiHuYeZiCardProto.BroadcastShuiHuYeZiCardRespMsg.Builder builderRoundShuiHuYeZiCardRespMsg(int curRound, long winnerId, long playerId1, ShuiHuYeZiCardBattleCard playCard1, long playerId2, ShuiHuYeZiCardBattleCard playCard2, long roundTime, int buffId, int roomType) {
        ShuiHuYeZiCardProto.BroadcastShuiHuYeZiCardRespMsg.Builder broadcastType1 = ShuiHuYeZiCardProto.BroadcastShuiHuYeZiCardRespMsg.newBuilder();
        broadcastType1.setType(1);
        // 对方 targetId
        ShuiHuYeZiCardProto.ShuiHuYeZiCardRoundInfo.Builder roundInfo = ShuiHuYeZiCardProto.ShuiHuYeZiCardRoundInfo.newBuilder();
        roundInfo.setRound(curRound);
        ShuiHuYeZiCardProto.ShuiHuYeZiCardRecord.Builder cardRecord = ShuiHuYeZiCardProto.ShuiHuYeZiCardRecord.newBuilder();

        cardRecord.addUserRecordList(ShuiHuYeZiCardCommonMgr.builderShuiHuYeZiCardRoundUserRecord(playerId1, playCard1));
        cardRecord.addUserRecordList(ShuiHuYeZiCardCommonMgr.builderShuiHuYeZiCardRoundUserRecord(playerId2, playCard2));
        cardRecord.setWinnerId(winnerId);
        cardRecord.setBuffId(buffId);
        roundInfo.setRecord(cardRecord);
        roundInfo.setBuffId(getRoomInfo().getBuffId());
        roundInfo.setNum(getRoomInfo().getNum());
        roundInfo.setNextBuffId(getRoomInfo().getNextBuffId());
        roundInfo.setRoundEndTime(roundTime);
        roundInfo.setRoomType(roomType);
        broadcastType1.setRoundInfo(roundInfo);

        return broadcastType1;
    }

    /**
     * 比赛是否结束
     *
     * @return
     */
    abstract public boolean isOver();

    /**
     *  游戏结束
     */
    abstract public void endGame();

    abstract public ShuiHuYeZiCardProto.ShuiHuYeZiCardRoomInfo.Builder builderShuiHuYeZiCardRoomInfo(long userId);

    public ShuiHuYeZiCardRoomData getRoomInfo() {
        return roomInfo;
    }

    /**
     * 刷新卡牌点数
     */
    public void refreshCard(ShuiHuYeZiCardActivityConfig activityConfig) {
        for (Map.Entry<Long, Map<Integer, ShuiHuYeZiCardBattleCard>> entry : roomInfo.getUserCardMap().entrySet()) {
            long userId = entry.getKey();
            Map<Integer, ShuiHuYeZiCardBattleCard> userCardMap = entry.getValue();
            ShuiHuYeZiCardBuffConfig buffConfig = activityConfig.getBuffConfigMap().get(roomInfo.getBuffId());
            for (ShuiHuYeZiCardBattleCard card : userCardMap.values()) {
                ShuiHuYeZiCardCardConfig cardConfig = activityConfig.getCardConfigMap().get(card.getId());
                // buff加成值
                int buffAddValue = 0;
                // level加成值
                int levelAddValue = cardConfig.levelPointMap.getOrDefault(card.getLevel(), 0);
                if (buffConfig != null && buffConfig.parList.get(1) == cardConfig.getType()) {
                    // 阵营
                    if (buffConfig.getType() == 1) {
                        // 手牌中有1张则点数
                        int num = getCampNum(activityConfig, userId, buffConfig.parList.get(1));
                        buffAddValue = buffConfig.parList.get(0) * num;
                    } else if (buffConfig.getType() == 2) {
                        // 弃牌堆中有1张，则点数+
                        int num = getDiscardListCampNum(activityConfig, buffConfig.parList.get(1));
                        buffAddValue = buffConfig.parList.get(0) * num;
                    } else if (buffConfig.getType() == 3) {
                        // 点数
                        buffAddValue = buffConfig.parList.get(0);
                    } else if (buffConfig.getType() == 4) {
                        // 战场上某阵营的所有卡平分x点，向上取整
                        int num = getBattlefieldCampNum(activityConfig, buffConfig.parList.get(1));
                        if (num != 0) {
                            // 向上取整
                            buffAddValue = (buffConfig.parList.get(0) + num - 1) / num;
                        }
                    }
                }
                if (card.getQuality() == 1) {
                    buffAddValue = buffAddValue * 2;
                }
                card.setValue(cardConfig.getPoint() + buffAddValue + levelAddValue);
//                logger.info("玩家id :{},cardId:{},buffAddValue:{},levelAddValue:{},basePoint:{},最终值value:{}",userId,card.getId(),buffAddValue,levelAddValue,cardConfig.getPoint(),card.getValue());
            }
//            logger.info("玩家id :{},当前buffId:{},buff剩余回合数：{}，手里卡牌信息:{},弃牌堆：{}",userId,getRoomInfo().getBuffId(),getRoomInfo().getNum(),userCardMap,getRoomInfo().getDiscardList());
        }
    }

    /**
     * 获取玩家某个阵营的玩家数量
     *
     * @return
     */
    private int getCampNum(ShuiHuYeZiCardActivityConfig activityConfig, long userId, int campType) {
        int num = 0;
        Map<Integer, ShuiHuYeZiCardBattleCard> userCardMap = roomInfo.getUserCardMap().get(userId);
        for (Integer cardId : userCardMap.keySet()) {
            ShuiHuYeZiCardCardConfig cardConfig = activityConfig.getCardConfigMap().get(cardId);
            if (cardConfig != null && cardConfig.getType() == campType) {
                num++;
            }
        }
        return num;
    }

    /**
     * 获取战场上某个阵营的卡牌数量
     *
     * @return
     */
    private int getBattlefieldCampNum(ShuiHuYeZiCardActivityConfig activityConfig, int campType) {
        int num = 0;
        for (Map<Integer, ShuiHuYeZiCardBattleCard> userCardMap : roomInfo.getUserCardMap().values()) {
            for (Integer cardId : userCardMap.keySet()) {
                ShuiHuYeZiCardCardConfig cardConfig = activityConfig.getCardConfigMap().get(cardId);
                if (cardConfig != null && cardConfig.getType() == campType) {
                    num++;
                }
            }
        }
        return num;
    }

    /**
     * 弃牌堆某个阵营 卡牌的数量
     *
     * @return
     */
    private int getDiscardListCampNum(ShuiHuYeZiCardActivityConfig activityConfig, int campType) {
        int num = 0;
        for (ShuiHuYeZiCardDiscardCard item : getRoomInfo().getDiscardList()) {
            ShuiHuYeZiCardCardConfig cardConfig = activityConfig.getCardConfigMap().get(item.getId());
            if (cardConfig != null && cardConfig.getType() == campType) {
                num++;
            }
        }

        return num;
    }

    /**
     * 随机buff
     *
     * @param activityConfig
     * @param round          要随机的回合数
     * @param excludeBuffId  排除 某个buffId的阵营
     * @return
     */
    private int randomBuffId(ShuiHuYeZiCardActivityConfig activityConfig, int round, int excludeBuffId) {
        int buffId = 0;
        ShuiHuYeZiCardBuffConfig excludeBuffConfig = activityConfig.getBuffConfigMap().get(excludeBuffId);
        Map<Integer, Integer> roundMap = activityConfig.getRoundBuffIdMap().get(round);
        if (roundMap == null) {
            return buffId;
        }
        Map<Integer, Integer> map = new HashMap<>(roundMap);
        if (excludeBuffConfig != null) {
            Iterator<Integer> iterator = map.keySet().iterator();
            while (iterator.hasNext()) {
                ShuiHuYeZiCardBuffConfig tempBuffConfig = activityConfig.getBuffConfigMap().get(iterator.next());
                if (tempBuffConfig != null && (tempBuffConfig.getType() == excludeBuffConfig.getType() || tempBuffConfig.parList.get(1).equals(excludeBuffConfig.parList.get(1)))) {
                    // 过滤 buff类型 或者 作用阵营一样的
                    iterator.remove();
                }
            }
        }
        if (map.size() > 0) {
            int sum = 0;
            for (Integer weight : map.values()) {
                sum += weight;
            }
            int value = random.nextInt(sum);
            for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
                if (value < entry.getValue()) {
                    buffId = entry.getKey();
                    break;
                }
                value -= entry.getValue();
            }
        }
        return buffId;
    }

    /**
     * 随机buff 回合数
     *
     * @return
     */
    private int randomBuffNum(ShuiHuYeZiCardActivityConfig activityConfig, int buffId) {
        ShuiHuYeZiCardBuffConfig buffConfig = activityConfig.getBuffConfigMap().get(buffId);
        if (buffConfig != null) {
            int sum = 0;
            for (Integer weight : buffConfig.roundMap.values()) {
                sum += weight;
            }
            int value = random.nextInt(sum);
            for (Map.Entry<Integer, Integer> entry : buffConfig.roundMap.entrySet()) {
                if (value < entry.getValue()) {
                    return entry.getKey();
                }
                value -= entry.getValue();
            }
        }
        return 0;
    }

    /**
     * 玩家是否胜利
     * 有剩余卡牌的获胜，如果都没了。取最近回合的胜利。如果都是平。那就都获胜
     *
     * @param userId
     * @return
     */
    public boolean isWin(long userId) {
        int userRemainNum = 0;
        int targetRemainNum = 0;

        for (Map.Entry<Long, Map<Integer, ShuiHuYeZiCardBattleCard>> entry : getRoomInfo().getUserCardMap().entrySet()) {
            if (entry.getKey() == userId) {
                userRemainNum = entry.getValue().size();
            } else {
                targetRemainNum = entry.getValue().size();
            }
        }
        if (userRemainNum > 0) {
            return true;
        } else if (targetRemainNum > 0) {
            return false;
        } else {
            return userId == getRoomInfo().getLastRoundWinnerId() || getRoomInfo().getLastRoundWinnerId() == 0;
        }
    }

    /**
     * 获胜玩家的id
     *
     * @return
     */
    public long getWinnerId() {
        long winnerId = 0;
        for (Map.Entry<Long, Map<Integer, ShuiHuYeZiCardBattleCard>> entry : getRoomInfo().getUserCardMap().entrySet()) {
            if (entry.getValue().size() > 0) {
                winnerId = entry.getKey();
            }
        }
        if (winnerId == 0) {
            winnerId = getRoomInfo().getLastRoundWinnerId();
        }
        return winnerId;
    }


    private ShuiHuYeZiCardDiscardCard copyShuiHuYeZiCardBattleCard(ShuiHuYeZiCardBattleCard shuiHuYeZiCardBattleCard) {
        ShuiHuYeZiCardDiscardCard discardCard = new ShuiHuYeZiCardDiscardCard();
        discardCard.setId(shuiHuYeZiCardBattleCard.getId());
        discardCard.setLevel(shuiHuYeZiCardBattleCard.getLevel());
        discardCard.setQuality(shuiHuYeZiCardBattleCard.getQuality());
        return discardCard;
    }

    /**
     * 计算卡牌的基础点数
     *
     * @return
     */
    private int calTotalCardPoint(ShuiHuYeZiCardActivityConfig activityConfig, List<Integer> cardList) {
        int totalPoint = 0;
        for (Integer cardId : cardList) {
            ShuiHuYeZiCardCardConfig cardConfig = activityConfig.getCardConfigMap().get(cardId);
            totalPoint += cardConfig.getPoint();
        }
        return totalPoint;
    }

    public static Random getRandom() {
        return random;
    }

    public static Logger getLogger() {
        return logger;
    }
}
